/*
 * Copyright 2010-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.pathlet.core.impl;

import org.pathlet.core.BeanPathConverter;
import org.pathlet.core.Path;
import org.pathlet.core.exception.ResourceAccessException;

import static org.pathlet.util.ValueUtils.notEmpty;

/**
 * Provide the common java class name convert function.
 * For example: <br/>
 *  If you want to map path "/somepackage/ServiceName" to java class "somepackage.support.PrefixServiceNameSuffix", <br/>
 *  you should create a new ServicePathConverter("support", "Prefix", "Suffix") setting it into Resource factory.
 *
 * @author Charlie Zhang
 *
 */
public class ClassNamePathConverter implements BeanPathConverter {

	private String appendPackage = "";

	private String namePrefix = "";

	private String nameSuffix = "";


	public ClassNamePathConverter() {  }

	public void setAppendPackage(String appendPackage) {
		if(appendPackage != null) {
			this.appendPackage = appendPackage.trim();
		}
	}

	public void setNamePrefix(String namePrefix) {
		if(namePrefix != null) {
			this.namePrefix = namePrefix.trim();
		}
	}

	public void setNameSuffix(String nameSuffix) {
		if(nameSuffix != null) {
			this.nameSuffix =  nameSuffix.trim();
		}
	}


	public String convertToType(Path resourcePath, Path basePath, String basePackage) throws ResourceAccessException {
		String basePathStr = basePath.getFullPath();
		if(basePathStr.endsWith("/") == false) {
			basePathStr = basePathStr + "/";
		}

		//Validate the resourcePath is start with prePath
		if(resourcePath.getDirectory().indexOf(basePathStr) != 0) {
			throw new ResourceAccessException("Failed to find resource path="
					+ resourcePath + ", The path must be start with '" + basePathStr + "'", resourcePath);
		}

		String relativePackage = (resourcePath.getDirectory()
				.substring(basePathStr.length())).replace(Path.SEPARATOR, '.');

		String fullClassName = basePackage + '.' + relativePackage
				+ ((this.appendPackage.length() > 0) ? (this.appendPackage + '.') : "")
				+ this.namePrefix + resourcePath.getNameWithoutSuffix() + this.nameSuffix;

		return fullClassName;
	}


	public Path converToPath(final String type, final Path basePath, final String basePackage) throws ResourceAccessException {
//		String basePathStr = basePath.getFullPath();
//		if(basePathStr.endsWith("/") == false) {
//			basePathStr = basePathStr + "/";
//		}
		String basePkg = basePackage;
		if(basePackage.endsWith(".")) {
			basePkg = basePackage.substring(0, basePackage.length() - 1);
		}

		if(type.startsWith(basePkg) == false) {
			throw new ResourceAccessException("Failed to convert type="
					+ type + " to path, The type must be start with '" + basePackage + "'");
		}

		boolean interfaceType = type.endsWith(this.nameSuffix) ? false : true;
		String[] packageAndName = getPackageAndName(type);

		//packageName 删除以 basePackage开头的部分
		String packageName = packageAndName[0].substring(basePkg.length() + 1);

		String pathStr = packageName.replace('.', Path.SEPARATOR);
		String name = packageAndName[1];

		if(basePath != null && basePath.isAbsolute()) {
			return new Path(new Path(basePath, pathStr), name);
		}
		else {
			return new Path(new Path(new Path("/"), pathStr), name);
		}
	}

	public String[] getPackageAndName(String type) {
		int lastSeparatorIdx = type.lastIndexOf('.');
		String name = type.substring(lastSeparatorIdx + 1, type.length());
		String packageName = type.substring(0, lastSeparatorIdx);
		int beginIndex = 0;
		int endIndex = name.length();

		if(notEmpty(this.namePrefix) && name.startsWith(this.namePrefix)) {
			beginIndex = this.namePrefix.length();
		}

		if(notEmpty(this.nameSuffix) && name.endsWith(this.nameSuffix)) {
			endIndex = name.length() - this.nameSuffix.length();
		}

		String convertedName = name.substring(beginIndex, endIndex);
		if(notEmpty(this.appendPackage)) {
			//清理appendPackage结尾的'.'
			String appendPackage = this.appendPackage.endsWith(".") ? this.appendPackage.substring(0, this.appendPackage.length() - 1) : this.appendPackage;

			if(packageName.endsWith(appendPackage)) {
				String convertedPackageName = packageName.substring(0, packageName.length() - appendPackage.length());
				return new String[]{convertedPackageName, convertedName};
			}
			else {
				return new String[]{packageName, convertedName};
			}
		}
		else {
			return new String[]{packageName, convertedName};
		}
	}

}
